package app.keter.portal.security.auth;

import app.keter.portal.base.BaseController;
import app.keter.portal.security.CurrentUser;
import app.keter.portal.security.SecurityService;
import app.keter.portal.security.core.UserDetailsImpl;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.jfinal.kit.JsonKit;
import com.keter.framework.core.util.ConcurrentUtil;
import com.keter.framework.web.result.JSONResult;
import com.keter.framework.web.result.ResultUtil;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

@RestController
public class AuthController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(AuthController.class);
    @Value("${jwt.header}")
    private String header;
    @Value("${jwt.tokenHead}")
    private String tokenHeader;

    @Autowired
    private AuthService authenService;

    @Autowired
    private SecurityService security;

    ListeningExecutorService service = ConcurrentUtil.service();

    @PostMapping(value = "/authenticate")
    public JSONResult authenticate(@RequestBody JSONObject authObject) throws AuthenticationException{
        Preconditions.checkNotNull(authObject);
        final String token = authenService.login(
                authObject.getString("username"),
                authObject.getString("password")
        );
        return ResultUtil.wrap(token);
    }

    @GetMapping(value = "/tokenrefresh")
    public JSONResult refresh(HttpServletRequest request) throws AuthenticationException{
        String token = request.getHeader(header).substring(tokenHeader.length());
        return authenService.refresh(token);
    }

    @GetMapping(value = "/auth/me")
    public JSONResult me() throws AuthenticationException {
        JSONObject me = new JSONObject();
//        UserDetailsImpl currentUser = SecurityService.getCurrentUser();
        UserDetailsImpl currentUser = CurrentUser.getCurrentUser();
        me.put("id",CurrentUser.getCurrentUser().getId());
        me.put("username",CurrentUser.getCurrentUser().getUsername());
        me.put("roles",CurrentUser.getCurrentUser().getAuthorities());
        ConcurrentUtil.result(() -> {
            // 新线程内无法直接读取当前用户，需要显示传入
            Validate.notNull(currentUser,"当前用户不能为空!");
        },service);
        return wrap(me);
    }

    @HystrixCommand(fallbackMethod = "error")
    @GetMapping(value = "/auth/me/hys")
    public String meOfHys(HttpServletRequest request) throws AuthenticationException {
        if(request!=null) {
            logger.info("token:{}", request.getHeader("XAuthorization"));
        }
        Validate.notNull(CurrentUser.getCurrentUser());
        return JsonKit.toJson(CurrentUser.getCurrentUser());
    }

    /**
     * 熔断机制的回调方法
     * @param t
     * @return
     */
    public String error(HttpServletRequest request, Throwable t) {
        logger.error("", t);
        return null;
    }
}
